import logging
import smtplib
from email.mime.text import MIMEText

import requests
from msal import ConfidentialClientApplication

from app.config import settings


def send_email(to_email: str, subject: str, body: str):
    """
    发送邮件。
    """
    try:
        if settings.send_email_type == "gmail":
            send_email_with_gmail(to_email, subject, body)
        elif settings.send_email_type == "techtanium":
            send_email_with_techtanium(to_email, subject, body)
        else:
            raise ValueError(f"Invalid send_email_type: {settings.send_email_type}")
    except Exception as e:
        raise e

def send_email_with_gmail(to_email: str, subject: str, body: str):
    msg = MIMEText(body, 'plain', 'utf-8')
    msg['Subject'] = subject
    msg['From'] = settings.smtp_from
    msg['To'] = to_email
    try:
        with smtplib.SMTP(settings.smtp_host, settings.smtp_port) as s:
            s.starttls()
            s.login(settings.smtp_user, settings.smtp_password)
            s.send_message(msg)
    except Exception as e:
        raise e


def send_email_with_techtanium(to_email: str, subject: str, body: str):
    sender_email = settings.techtanium_sender
    client_id = settings.techtanium_client_id
    tenant_id = settings.techtanium_tenant_id
    client_secret = settings.techtanium_client_secret

    # get token
    app = ConfidentialClientApplication(
        client_id,
        authority=f"https://login.microsoftonline.com/{tenant_id}",
        client_credential=client_secret,
    )
    token = app.acquire_token_for_client(scopes=["https://graph.microsoft.com/.default"])
    if "access_token" not in token:
        raise Exception(f"Get token failed: {token}")
    access_token = token["access_token"]

    # list tenant emails
    headers = {"Authorization": f"Bearer {access_token}"}
    url = "https://graph.microsoft.com/v1.0/users?$select=mail,userPrincipalName&$top=999"
    resp = requests.get(url, headers=headers)
    if resp.status_code != 200:
        raise Exception(f"Failed to list users: {resp.status_code}, {resp.text}")
    users = resp.json().get("value", [])
    emails = [u["mail"] for u in users if u.get("mail")]

    if sender_email not in emails:
        raise Exception(f"Failed to send email to {sender_email}: {sender_email} is not a valid tenant email")

    # send email
    headers = {"Authorization": f"Bearer {access_token}"}
    url = f"https://graph.microsoft.com/v1.0/users/{sender_email}/sendMail"
    payload = {
        "message": {
            "subject": subject,
            "body": {"contentType": "Text", "content": body},
            "toRecipients": [{"emailAddress": {"address": to_email}}],
        }
    }
    resp = requests.post(url, headers=headers, json=payload)
    if resp.status_code != 202:
        raise Exception(f"Failed to send email: {resp.status_code}, {resp.text}")
